package com.cltech.service.sys.impl;

import com.cltech.dto.SysPermissionDto;
import com.cltech.dto.TreeNode;
import com.cltech.entity.sys.SysPermission;
import com.cltech.entity.sys.SysRole;
import com.cltech.entity.sys.SysUser;
import com.cltech.frame.base.impl.BaseServiceImpl;
import com.cltech.frame.result.ResponseBean;
import com.cltech.frame.specification.PredicateBuilder;
import com.cltech.frame.specification.Specifications;
import com.cltech.frame.specification.utils.SpecificationSortUtil;
import com.cltech.mapper.SysPermissionMapper;
import com.cltech.repository.sys.SysPermissionRepository;
import com.cltech.service.sys.SysPermissionService;
import com.cltech.util.TreeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static java.util.stream.Collectors.toSet;

/**
 * Created by Administrator on 2019/4/14.
 */
@Service("sysPermissionService")
public class SysPermissionServiceImpl extends BaseServiceImpl<SysPermission, String> implements SysPermissionService {
    private SysPermissionRepository sysPermissionRepository;

    @Autowired
    private SysPermissionMapper sysPermissionMapper;

    @Autowired
    public void setSysUserRepository(SysPermissionRepository sysPermissionRepository) {
        this.sysPermissionRepository = sysPermissionRepository;
        super.setBaseRepository(sysPermissionRepository);
    }

    @Override
    public Page<SysPermissionDto> findAll(Map<String, String[]> queryParameters, int pageNo, int pageSize) {
        Map<String, Object> map = SpecificationSortUtil.creat(queryParameters, SysPermission.class);
        Specification<SysPermission> specification = (Specification<SysPermission>) map.get(SpecificationSortUtil.SEARCHS);
        Sort sort = (Sort) map.get(SpecificationSortUtil.ORDERS);
        Pageable page = null == sort ? new PageRequest(0, 15) : new PageRequest(0, 15, sort);
        if (null == specification) {
            return sysPermissionMapper.entityToDto(sysPermissionRepository.findAll(page));
        } else {
            return sysPermissionMapper.entityToDto(sysPermissionRepository.findAll(specification,
                    page));
        }
    }

    @Override
    public ResponseBean<List<TreeNode>> permissionTree(Map<String, String[]> queryParameters) {
        Map<String, Object> map = SpecificationSortUtil.creat(queryParameters, SysPermission.class);
        Specification<SysPermission> specification = (Specification<SysPermission>) map.get(SpecificationSortUtil.SEARCHS);
        List<SysPermission> sysPermissions ;
        if (null == specification) {
            sysPermissions = sysPermissionRepository.findAll();
        } else {
            sysPermissions = sysPermissionRepository.findAll(specification);
        }
        List treeNodes = TreeUtil.buildTree(sysPermissionMapper.entityToTreeNode(sysPermissions));
        return ResponseBean.success(treeNodes);
    }

    @Override
    public ResponseBean<List<TreeNode>> findPermissionsTreeByRole(String roleCode, String sysPermissionType, Integer sysPermissionlevel) {
        Specification<SysPermission> specification  = Specifications.<SysPermission>and()
                .eq(!StringUtils.isEmpty(roleCode),"roles.id",roleCode)
                .eq(!StringUtils.isEmpty(sysPermissionType),"type",sysPermissionType)
                .eq(null != sysPermissionlevel,"level",sysPermissionlevel).build();
        List<SysPermission> sysPermissions = sysPermissionRepository.findAll(specification);
        List treeNodes = TreeUtil.buildTree(sysPermissionMapper.entityToTreeNode(sysPermissions));
        return ResponseBean.success(treeNodes);
    }

    @Override
    public ResponseBean<List<TreeNode>> findAllPermissionsTreeByRole(String roleId, String sysPermissionType, Integer sysPermissionlevel) {
        List<TreeNode> res = sysPermissionRepository.findAllPermissionsTreeByRole(roleId, sysPermissionType, sysPermissionlevel);
        List treeNodes = TreeUtil.buildTree(res);;
        return ResponseBean.success(treeNodes);
    }


    @Override
    public ResponseBean<List<TreeNode>> findPermissionsTreeByUser(String userId, String sysPermissionType, Integer sysPermissionlevel) {
        Specification<SysPermission> specification  = Specifications.<SysPermission>and()
                .eq(!StringUtils.isEmpty(sysPermissionType),"type",sysPermissionType)
                .eq(null != sysPermissionlevel,"level",sysPermissionlevel)
                .predicate(!StringUtils.isEmpty(userId), ((root, query, cb) -> {
                    Join roles = root.join("roles", JoinType.INNER);
                    Join users = roles.join("users",JoinType.INNER);
                    return cb.equal(users.get("id"), userId);
                })).build();
        List<SysPermission> sysPermissions = sysPermissionRepository.findAll(specification);
        List treeNodes = TreeUtil.buildTree(sysPermissionMapper.entityToTreeNode(sysPermissions));
        return ResponseBean.success(treeNodes);
    }

    @Override
    public ResponseBean<Set<SysPermission>> findByIdIsIn(List<String> ids) {
        return ResponseBean.success(sysPermissionRepository.findByIdIsIn(ids));
    }

    @Override
    public ResponseBean<SysPermission> findByPermissionCode(String permissionCode) {
        return ResponseBean.success(sysPermissionRepository.findByPermissionCode(permissionCode));
    }

    @Override
    public ResponseBean<SysPermission> addOrUpdate(SysPermissionDto dto) {
        SysPermission entity = sysPermissionMapper.dtoToEntity(dto);
        SysPermission parent = null;
        if (!StringUtils.isEmpty(dto.getParentId())) {
            parent = findById(dto.getParentId()).getData().orElse(null);
        }
        String id = entity.getId();
        String permissionCode = entity.getPermissionCode();
        if (StringUtils.isEmpty(id)) {
            if (null != findByPermissionCode(permissionCode).getData()) {
                return ResponseBean.fail("权限资源编码已存在，新增权限资源失败");
            }
            entity.setCreateTime(new Date());
            if (null != parent) {
                entity.setParent(parent);
                entity.setParentIds(StringUtils.isEmpty(parent.getParentIds())
                        ? parent.getId() : parent.getParentIds() + "," + parent.getId());
            }
            return save(entity);
        } else {
            SysPermission entityOld = findById(id).getData().orElse(null);
            if (null != entityOld) {
                entityOld.setUpdateTime(new Date());
                entityOld.setDescription(entity.getDescription());
                entityOld.setName(entity.getName());
                if (!entity.getPermissionCode().equals(entityOld.getPermissionCode())) {
                    if (null != findByPermissionCode(permissionCode).getData()) {
                        return ResponseBean.fail("权限资源编码已存在，新增权限资源失败");
                    }
                    entityOld.setPermissionCode(entity.getPermissionCode());
                    if (null != parent) {
                        entityOld.setParent(parent);
                        entityOld.setParentIds(StringUtils.isEmpty(parent.getParentIds())
                                ? parent.getId() : parent.getParentIds() + "," + parent.getId());

                    }
                    return save(entityOld);
                }
            }
            return ResponseBean.fail("更新权限资源编");
        }
    }
}
